/// Created by Nazariy Jaworski Copyright (c) 2013
/// Bot program
///
/// botcommunicator.h -
///  implements communication between bots on
///  different machines
///
/// To Do list:
///  - ...
///
/// v 0.1        08.04.2013

#ifndef BOTCOMMUNICATOR_H
#define BOTCOMMUNICATOR_H

// Some default values
#define DEFAULT_REQUEST_MESSAGE_COUNT   5
#define DEFAULT_REQUEST_MESSAGE_WAIT    5000

#define DEFAULT_TCP_SERVER_PORT         10001
#define DEFAULT_UDP_PORT                10002

#define MESSAGE_REQUEST                 "$$$$"
#define MESSAGE_ACCEPT                  "####"

#define MESSAGE_PING                    "ping"
#define MESSAGE_PONG                    "pong"

#define UI_STR_MESSAGE_UDP_INPUT        " UDP data input: "
#define UI_STR_MESSAGE_TCP_INPUT        " TCP data input: "
#define UI_STR_MESSAGE_UDP_OUTPUT       " UDP data output: "
#define UI_STR_MESSAGE_TCP_OUTPUT       " TCP data output: "

#include "botserver.h"
#include <iostream>
#include <QtNetwork/qtcpsocket.h>
#include <QtNetwork/qudpsocket.h>

/// Communicator of a Bot - implements communication
/// between bots on different machines
class BotCommunicator : public QObject

{
    Q_OBJECT

    public: enum BotState
    {
        IsNotRegistered,
        IsRegistered
    };
    public: BotState   myState;             ///< Default - IsNotRegistered

    // Defenition of his main objects
    public: BotServer  *myServer = nullptr;           ///< Server implementation, if Bot owns the BotServer
    public: QTcpSocket *myQTcpSocket = nullptr;       ///< For communications, if Bot is a client

    public: QUdpSocket *myQUdpInputSocket = nullptr;
    public: QUdpSocket *myQUdpOutputSocket = nullptr;

    public: BotCommunicator(QObject *parent = NULL);///< Common constructor

    public: void Init();                    ///< Initialization

    private: void RunBotServer();           ///< Runs Bot in BotServer mode

    /// Try to register at environment, try to find a BotServer and connect to it,
    /// or become the BotServer. Use the paremeter to set the automat satage.
    public: Q_SLOT void RegisterAtEnvironment(int parameter = 0);

    public: Q_SLOT void ShowClients() const;
    ///< emits simple strings, that shows list of connected clients

    public: Q_SLOT void WriteToTcpSocket();  ///< Writes data into TCP Socket

    private: Q_SLOT void OnTcpSocketInput(); ///< Processing TCP input data

    private: Q_SLOT void OnUdpSocketInput(); ///< Processing UDP input data

    private: Q_SLOT void OnTcpSocketDisconnected();
    ///< Process network TCP errors

    private: Q_SLOT void OnTcpSocketError(QAbstractSocket::SocketError socketError);
    ///< Process network TCP errors

    private: Q_SLOT void OnUdpInputSocketError(QAbstractSocket::SocketError socketError);
    ///< Process network UDP errors

    private: Q_SLOT void OnUdpOutputSocketError(QAbstractSocket::SocketError socketError);
    ///< Process network UDP errors

    public: ~BotCommunicator();             ///< Common destructor
};

#endif // BOTCOMMUNICATOR_H
